from flask import current_app, jsonify
from flask import g
from flask import request
from flask import session

from info import constants, db
from info import redis_store
from info.models import User, Category, News
from info.utils.response_code import RET
from . import news_blue
from flask import render_template
from info.utils.commons import login_required



@news_blue.route('/')
@login_required
def index():
    """
    1/查看是否有缓存的user_id，有就和数据库中对比
    2/查询新闻列表，并排序显示
    3/查询点击排行
    4/右上角登录和注册切换

    """
    #先查询缓存中是否有用户
    user = g.user
    #查询新闻分类
    try:
        categorys = Category.query.all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询新闻分类数据失败')
    #判断是否有新闻
    if not categorys:
        return jsonify(errno=RET.NODATA,errmsg='无新闻分类数据')
    #把新闻分类对象添加到列表中
    category_list = []
    for category in categorys:
        category_list.append(category.to_dict())

    #新闻点击排行
    #根据新闻点击数降序排行查询10条：10个新闻对象
    try:
        news_list = News.query.order_by(News.clicks.desc()).limit(constants.HOME_PAGE_MAX_NEWS)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询新闻排行数据失败')
    #判断新闻对象非空
    if not news_list:
        return jsonify(errno=RET.NODATA,errmsg='无新闻排行数据')
    #把每个新闻对象的to_dict添加到列表中
    news_clicks_list = []
    for news in news_list:
        news_clicks_list.append(news.to_dict())

    #添加返回数据
    data = {
        'user_info':user.to_dict() if user else None,
        'category_list':category_list,
        'news_clicks_list':news_clicks_list,
    }
    return render_template('news/index.html',data=data)



# 项目favicon.ico文件的加载
@news_blue.route('/favicon.ico')
def favicon():
    """
    http://127.0.0.1:5000/favicon.ico
    实现/favicon.ico路径下的图标加载
    1、favicon图标的加载，不是每次请求都加载，是浏览器默认实现的，如果有缓存，必须要清除缓存，
    2、把浏览器彻底关闭，重启浏览器。
    :return:
    """
    # 使用current_app调用flask内置的函数，发送静态文件给浏览器，实现logo图标的加载
    return current_app.send_static_file('news/favicon.ico')


@news_blue.route('/news_list')
def get_news_list():
    """
    请求方式是get，获取参数：新闻分类id；第几页（没有数据，默认第一页）；一页有几条数据（没有数据，默认10条）
    1/获取参数cid,page,per_page
    2/校验参数的类型
    3/根据cid查询数据库获取新闻；如果用户选择最新则查询所有
    4/获取分页后的数据，总页数，当前页，新闻列表
    4/返回响应
    :return:
    """
    #获取参数
    cid = request.args.get('cid',1)
    page = request.args.get('page',1)
    per_page = request.args.get('per_page',10)
    #转换数据类型
    try:
        cid,page,per_page = int(cid),int(page),int(per_page)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR,errmsg='数据格式错误')
    # 定义容器
    filters = []
    if cid>1:
        filters.append(News.category_id==cid)
    try:
        paginate = News.query.filter(*filters).order_by(News.create_time.desc()).paginate(page,per_page,False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询数据失败')
    #获取分页后的数据
    news_list = paginate.items
    total_page = paginate.pages
    current_page = paginate.page
    #定义容器，保存查询到的数据
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_dict())
    #返回字典
    data = {
        'news_dict_list':news_dict_list,
        'total_page':total_page,
        'current_page':current_page
    }
    return jsonify(errno=RET.OK,errmsg='OK',data=data)

@news_blue.route('/<int:news_id>')
@login_required
def get_news_detail(news_id):
    """
    1/获取参数：新闻id
    2/验证参数是否在数据库中
    :return:
    """
    user = g.user
    #新闻点击排行
    #查询数据库得到新闻对象
    try:
        news_list = News.query.order_by(News.clicks.desc()).limit(constants.HOME_PAGE_MAX_NEWS)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询数据失败')
    #判断新闻对象是否为空
    if not news_list:
        return jsonify(errno=RET.NODATA,errmsg='无新闻数据排行')
    #存储在容器方便返回
    news_list_click = []
    for news in news_list:
        news_list_click.append(news.to_dict())
    #新闻详情数据
    #根据id查询新闻
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='没有查到新闻数据')
    #判断新闻不为空
    if not news:
        return jsonify(errno=RET.NODATA,errmsg='无新闻数据')
    #新闻收藏
    is_collected = False
    #查看新闻是否被收藏
    if user:
        if news in user.collection_news:
            is_collected = True
    data = {
        'user_info':user.to_dict() if user else None,
        'news_list_click':news_list_click,
        'news_detail':news.to_dict(),
        'is_collected':is_collected
    }
    return render_template('news/detail.html',data=data)

@news_blue.route('/news_collect',methods=['POST'])
@login_required
def news_collect():
    """
    新闻收藏与取消
    点击收藏或者非收藏时，判断用户是否登录，接受参数判断新闻id是否在数据库，判断用户是否收藏，提交
    1/获取参数：news_id,action(collect,cancel_collect)
    2/校验参数,判断new_id是否在数据库，判断action是否为收藏或非收藏
    3/逻辑处理
    4/返回响应
    :return:
    """
    #判断用户是否登录
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR,errmsg='未登录')
    #接收前端点击时传的参数
    news_id = request.json.get('news_id')
    action = request.json.get('action')
    if not all([news_id,action]):
        return jsonify(errno=RET.PARAMERR,errmsg='查询参数失败')
    #判断参数，防止第三方查询
    try:
        news = int(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR,errmsg='参数类型错误')
    #判断参数范围
    if action not in ['collect','cancel_collect']:
        return jsonify(errno=RET.PARAMERR,errmsg='参数类型错误')
    #查询数据
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询新闻数据失败')
    if not news:
        return jsonify(errno=RET.NODATA,errmsg='没有数据')
    #如果前端传的数据是收藏，如果用户之前没有收藏过
    if action == 'collect':
        if news not in user.collection_news:
            user.collection_news.append(news)
    else:
        user.collection_news.remove(news)
    #提交
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR,errmsg='保存数据失败')
    return jsonify(errno=RET.OK,errmsg='OK')

